#include "MyClient.h"

int parsOrder(char *buf, char *paras)
{
    char clibuf[128] = {0};
    char *p = buf;
    int i = 0;
    int c = 1;
    while (*(p + i) != 0)
    {
        if (*(p + i) == ' ' || *(p + i) == '\n')
        {
            if (c == 1)
            {
                strncpy(clibuf, p, i);
                c++;
            }
            else if (c == 2)
            {
                strncpy(paras, p, i);
                c++;
            }
            p = p + i + 1;
            i = 0;
        }
        i++;
    }
    // puts(clibuf);
    // puts(paras);
    //  sscanf(buf, "%s %s", clibuf, paras);
    if (strncmp(clibuf, "signup", 6) == 0)
    {
        return signup;
    }
    else if (strncmp(clibuf, "login", 5) == 0)
    {
        return login;
    }
    else if (strncmp(clibuf, "cd", 2) == 0)
    {
        return cli_cd;
    }
    else if (strncmp(clibuf, "ls", 2) == 0)
    {
        return cli_ls;
    }
    else if (strncmp(clibuf, "push", 4) == 0)
    {
        return cli_pushs;
    }
    else if (strncmp(clibuf, "poll", 4) == 0)
    {
        return cli_polls;
    }
    else if (strncmp(clibuf, "remove", 4) == 0)
    {
        return cli_remove;
    }
    else if (strncmp(clibuf, "pwd", 3) == 0)
    {
        return cli_pwd;
    }
    else if (strncmp(clibuf, "mkdir", 5) == 0)
    {
        return cli_mkdir;
    }
    // puts("-1!!");
    return -1;
}
int firstConnection(int netfd, struct sockaddr_in *serverAddr, userInfo_t *userInfo)
{
    int ret = connect(netfd, (struct sockaddr *)serverAddr, sizeof(*serverAddr));
    ERROR_CHECK(ret, -1, "connect");
    // puts(userInfo->password);
    sendInfo(netfd, userInfo, sizeof(userInfo_t));
    int si;
    recvInfo(netfd, &si);
    return si;
}

int main(int argc, char *argv[])
{
    ARGS_CHECK(argc, 3);
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(atoi(argv[2]));
    serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
    // argv[1] "192.168.118.128" --> 32bit的大端ip地址
    userInfo_t userInfo;
    bzero(&userInfo, sizeof(userInfo));
    userInfo.pos = -1;
    int si = -1;
    while (1)
    {
        int netfd = socket(AF_INET, SOCK_STREAM, 0);
        // puts(userInfo.username);
        // puts(userInfo.password);
        // puts(userInfo.rootId);
        // printf("present pos:%d\n", userInfo.pos);
        printf("Server>");
        setbuf(stdout, NULL);
        setbuf(stdin, NULL);
        char clibuf[128] = {0};
        fgets(clibuf, 128, stdin);
        char paras[128] = {0};
        int jobType = parsOrder(clibuf, paras);

        int si = firstConnection(netfd, &serverAddr, &userInfo); // checkjpassword、taken
        // printf("jobType:%d si:%d\n", jobType, si);
        if (jobType > 1)
        { // valid jobType
            if (si == -1)
            {
                puts("token faliure, please signup Or login!!");
                puts("---------------------------------------------");
                close(netfd);
                continue;
            }
            else
            {
                puts("checked user!!");
            }
        }
        else if (jobType > -1)
        {
            // si!=-1已经登录，再次登录
            if (si != -1)
            {
                puts("already login!!");
                puts("---------------------------------------------");
                close(netfd);
                continue;
            }
        }
        sendInfo(netfd, &jobType, sizeof(jobType));

        switch (jobType)
        {
        case signup: // 注册
        {
            si = -1;
            recvInfo(netfd, &si);
            if (si == -1)
            {
                break;
            }
            puts("connectd!!!");
            puts("input name (namelen<=30):");
            printf("Server>");
            fflush(stdout);
            scanf("%s", userInfo.username); // name<=30
            puts("input password (passwordlen<=8):");
            printf("Server>");
            fflush(stdout);
            scanf("%s", userInfo.password); // password<=8
            sendInfo(netfd, &userInfo, sizeof(userInfo));
            recvInfo(netfd, &userInfo);
        }
        break;
        case login:
        {
            puts("input name (namelen<=30):");
            printf("Server>");
            setbuf(stdout, NULL);
            scanf("%s", userInfo.username); // name<=30
            sendInfo(netfd, &userInfo, sizeof(userInfo));
            recvInfo(netfd, &si);
            if (si == -1)
            {
                puts("user not find!!");
            }
            else
            {
                // puts("finding user Information...");
                char salt[32] = {0};
                recvInfo(netfd, salt);
                // puts(salt);
                puts("input password (passwordlen<=8):");
                printf("Server>");
                setbuf(stdout, NULL);
                scanf("%s", userInfo.password); // name<=30
                packPassword(salt, userInfo.password);
                // puts(userInfo.password);
                sendInfo(netfd, userInfo.password, sizeof(userInfo.password));
            }
            recvInfo(netfd, &si);
            // printf("si:%d\n", si);
            if (si == si_success)
            {
                int ret = recvInfo(netfd, &userInfo);
                puts("Login success!!");
            }
            else
            {
                puts("Login failure!!");
            }
        }
        break;
        case print:

            break;
        case cli_cd:
            if (strlen(paras))
            {
                si = 1;
                sendInfo(netfd, &si, sizeof(si));
                sendInfo(netfd, paras, strlen(paras));
                int si = -1;
                recvInfo(netfd, &si);
                if (si == 0)
                {
                    puts("no such dir");
                }
                else
                {
                    recvInfo(netfd, &userInfo);
                }
            }
            else
            {
                si = 0;
                sendInfo(netfd, &si, sizeof(si));
                puts("paras not enough!!");
            }

            break;
        case cli_ls:
        {
            char buf[4096] = {0};
            recvInfo(netfd, buf);
            puts("---------------------------------------------");
            printf("%s", buf);
        }
        break;
        case cli_pushs:
        {
            if (strlen(paras) == 0)
            {
                si = si_failure;
                sendInfo(netfd, &si, sizeof(si));
                break;
            }
            si = si_success;
            sendInfo(netfd, &si, sizeof(si));
            char filePath[64] = {0};
            strcpy(filePath, "./data/file2"); // paras,自己控制对错
            unsigned char MD[64] = {0};
            char MDStr[64] = {0};
            GenFileMD(filePath, MD);
            MDtoStr(MD, MDStr);
            // puts(MDStr);
            sendInfo(netfd, MDStr, strlen(MDStr));
            int si = -1;
            recvInfo(netfd, &si);
            if (si == 0)
            {
                sendFile(netfd, filePath);
            }
            sendFilename(netfd, filePath);
            recvInfo(netfd, &si);
            if (si == 0)
            {
                puts("receive failure!!");
            }
            else
            {
                puts("file received!!");
            }
        }
        break;
        case cli_polls:
        {
            if (strlen(paras) == 0)
            {
                si = si_failure;
                sendInfo(netfd, &si, sizeof(si));
                break;
            }
            si = si_success;
            sendInfo(netfd, &si, sizeof(si));
            sendFilename(netfd, paras);
            recvInfo(netfd, &si);
            if (si == si_failure)
            {
                puts("file not exist!!");
                puts("---------------------------------------------");
                close(netfd);
                break;
            }
            char md5[64] = {0};
            recvInfo(netfd, md5);
            char downloadPath[64] = {0};
            strcpy(downloadPath, "./data"); // paras,自己控制对错，暂时默认路径
            recvFile(netfd, downloadPath, paras);
            char filePath[128] = {0};
            sprintf(filePath, "%s/%s", downloadPath, paras);
            unsigned char MD[64] = {0};
            char MDStr[64] = {0};
            GenFileMD(filePath, MD);
            MDtoStr(MD, MDStr);
            if (strcmp(MDStr, md5) != 0)
            {
                puts("receive failure!!");
                unlink(filePath);
            }
            else
            {
                puts("file received!!");
            }
        }

        break;
        case cli_remove:

            break;
        case cli_pwd:
        {
            char m_path[256] = {0};
            recvInfo(netfd, m_path);
            puts(m_path);
            break;
        }
        case cli_mkdir:
        {
            if (strlen(paras))
            {
                si = 1;
                sendInfo(netfd, &si, sizeof(si));
                sendInfo(netfd, paras, strlen(paras));
            }
            else
            {
                si = 0;
                sendInfo(netfd, &si, sizeof(si));
            }
        }
        break;
        default:
            printf("jobType:%d\n", jobType);
            puts("invalid order Or not login!!");
            break;
        }
        puts("---------------------------------------------");
        close(netfd);
    }
}